package com.dingreading.cloud.soms.controller;

import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.data.RichTextStringData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dingreading.cloud.common.base.R;
import com.dingreading.cloud.common.dto.LoginDataDto;
import com.dingreading.cloud.common.dto.StaffRoleDto;
import com.dingreading.cloud.common.util.*;
import com.dingreading.cloud.common.util.excel.ExcelHandler;
import com.dingreading.cloud.common.util.excel.RowBean;
import com.dingreading.cloud.soms.dto.CaCallNamesDto;
import com.dingreading.cloud.soms.dto.CallMemberDto;
import com.dingreading.cloud.soms.dto.vo.CallNameVo;
import com.dingreading.cloud.soms.entity.*;
import com.dingreading.cloud.soms.service.*;
import com.dingreading.cloud.soms.util.LoginInfoUtil;
import com.dingreading.cloud.soms.util.ScheduleUtil;
import com.google.common.collect.Lists;
import com.mybatisflex.core.paginate.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/front/caCallName/v2")
@Api(tags = "门店-会员点名记录管理V2")
public class FrontCaCallNameControllerV2 {

    @Resource
    protected CaCallNamesService callNameService;
    @Resource
    protected CaScheduleService scheduleService;
    @Resource
    protected CaScheduleLessonService scheduleLessonService;
    @Resource
    protected StaffRolesService staffRolesService;
    @Resource
    protected StoresService storesService;
    @Resource
    protected MembersService membersService;
    @Resource
    protected StaffService staffService;


    @ApiOperation(value = "会员活动记录分页列表v2")
    @PostMapping(value = "/pageList")
    public R<Object> pageList(
            HttpServletRequest request,
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "分页公共类") PageUtil pageUtil,
            @ApiParam(value = "会员姓名/手机号/社团名/活动室名") @RequestParam(value = "keyword", required = false) String keyword,
            @ApiParam(value = "参与状态 1.已到 2.迟到 3.请假 4.未到") @RequestParam(value = "callStatus", required = false) Integer callStatus,
            @ApiParam(value = "活动状态 -1.已取消 0.未进行 1.已进行 2.已完成") @RequestParam(value = "status", required = false) Integer status,
            @ApiParam(value = "主讲导读username") @RequestParam(value = "teacherUid", required = false) String teacherUid,
            @ApiParam(value = "活动服务uid") @RequestParam(value = "projectUid", required = false) String projectUid,
            @ApiParam(value = "活动开始日期") @RequestParam(value = "beginDate", required = false) String beginDate,
            @ApiParam(value = "活动结束日期") @RequestParam(value = "endDate", required = false) String endDate
    ) {
        R<Object> r = LoginInfoUtil.getLoginDto(request);
        if (R.isError(r)) return r;
        LoginDataDto loginDto = (LoginDataDto) r.getData();

        String username = loginDto.getUsername();
        StaffRoleDto roleDto = AccountUtil.getStaffRole(loginDto.getStoreRoles());
        if (null == roleDto)
            return R.fail("未发现员工的角色权限");

        int staffRole = roleDto.getRole();

        Page<CaCallNamesDto> page = callNameService.pageList(
                pageUtil, storeUid, keyword, callStatus, beginDate, endDate, teacherUid, projectUid, status,
                staffRole, username
        );

        PageBeanDto data = new PageBeanDto();
        data.setTotal(page.getTotalRow());
        data.setList(page.getRecords());
        return R.ok(data);
    }

    @ApiOperation(value = "获取活动的已点名记录")
    @PostMapping(value = "/getCallNames", produces = "application/json; charset=UTF-8")
    public R<Object> getCallNames(
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "活动uid") @RequestParam(value = "lessonUid") String lessonUid
    ) {
        CaScheduleLesson lesson = scheduleLessonService.getLessonInfo(storeUid, lessonUid);
        if (null == lesson) return R.fail("活动获取失败");
        String lessonStoreUid = lesson.getStoreUid();
        if (lesson.getStatus().equals(-1)) {
            List<CallMemberDto> members = scheduleLessonService.getClassMemberAndCallMember(lessonStoreUid, lesson.getClassId(), lessonUid);
            return R.ok(members);
        } else {
            List<CaCallNamesDto> list = callNameService.getLessonCallNameDtos(lessonStoreUid, lessonUid);
            return R.ok(list);
        }
    }

    @ApiOperation(value = "开始活动点名")
    @PostMapping(value = "/callNames", produces = "application/json; charset=UTF-8")
    public R<Object> callNames(
            HttpServletRequest request,
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "活动uid") @RequestParam(value = "lessonUid") String lessonUid,
            @ApiParam(value = "会员参与json{memberUid:'',memberName:'',mob:'',callStatus:0}") @RequestParam(value = "callJson") String callJson
    ) throws Exception {
        R<Object> r = LoginInfoUtil.getLoginDto(request);
        if (R.isError(r)) return r;
        LoginDataDto loginDto = (LoginDataDto) r.getData();

        String username = loginDto.getUsername();
        List<LoginDataDto.StoreRolesBean> storeRole = loginDto.getStoreRoles();

        if (StringUtils.isBlank(callJson))
            return R.fail("会员到达json不能为空");

        CaScheduleLesson lesson = scheduleLessonService.getLessonInfo(storeUid, lessonUid);
        if (null == lesson) return R.fail("活动获取失败");
        if (lesson.getStatus().equals(-1)) return R.fail("活动已取消，不能点名");
        if (lesson.getStatus().equals(2)) return R.fail("活动已结束，不能点名");
        int studentNum = NepUtil.nullToZero(lesson.getStudentNum()) + NepUtil.nullToZero(lesson.getStudentTempNum());
        if (studentNum <= 0) return R.fail("活动下没有会员，不能点名");

        String lessonStoreUid = lesson.getStoreUid();
        String lessonStoreName = lesson.getStoreName();

        Stores stores = storesService.getByUid(lessonStoreUid);
        if (stores == null)
            return R.fail("未查询到门店信息");

        // 最新的主讲导读姓名
        Staff staff = staffService.getByUsername(lesson.getTeacherUid());
        if (staff == null)
            return R.fail("未查询到主讲导读");
        String teacherName = staff.getFullName();

        // 获取员工在门店的角色权限
        StaffRoles staffRole = staffRolesService.getStoreUidAndStaffUid(storeUid, staffUid);
        if (null == staffRole || StringUtils.isBlank(staffRole.getRoles()))
            return R.fail("员工角色权限获取失败");
        if (AccountUtil.isStoreManager(staffRole.getRoles())) {
            // 是店长，判断日期是否未到
            Date teachDate = DateUtil.parseDate(lesson.getTeachDate());
            Date nowDatetime = DateUtil.parseDate(DateUtil.getNowDateStr(), "yyyy-MM-dd");
            if (nowDatetime.getTime() < teachDate.getTime())
                return R.fail("活动日期未到：" + lesson.getTeachDate() + "，不能点名");
        } else {
            // 不是店长，是普通员工点名，判断主讲导读和日期
            if (!username.equals(lesson.getTeacherUid()))
                return R.fail("您不是本活动的主讲导读，不能点名");
            if (!lesson.getTeachDate().equals(DateUtil.getNowDateStr()))
                return R.fail("活动日期：" + lesson.getTeachDate() + "，不能点名");
        }

        JSONArray array = JSONArray.parseArray(callJson);
        Set<String> memberUids = new HashSet<>();
        for (int i = 0; i < array.size(); i++) {
            JSONObject object = array.getJSONObject(i);
            String memberUid = object.getString("memberUid");
            String memberName = object.getString("memberName");
            Integer callStatus = object.getInteger("callStatus");
            if (StringUtils.isBlank(memberUid) || null == callStatus || callStatus.equals(0))
                return R.fail("发现未被点名的会员：" + memberName + "，不能点名");
            if (memberUids.contains(memberUid))
                return R.fail("发现重复的会员：" + memberName + "，不能点名");
            memberUids.add(memberUid);
        }

        // 查询会员信息
        List<Members> membersList = membersService.getByUids(Lists.newArrayList(memberUids));
        if (CollectionUtils.isEmpty(membersList))
            return R.fail("点名的会员信息获取失败");
        Map<String, Long> memberMap = membersList.stream().collect(Collectors.toMap(Members::getUid, Members::getId));

        // 查找已有的点名记录
        List<CaCallNames> callNamesList = callNameService.listByStoreUidAndLessonUid(lessonStoreUid, lessonUid);
        Map<String, CaCallNames> callNamesMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(callNamesList))
            callNamesMap = callNamesList.stream().collect(Collectors.toMap(CaCallNames::getMemberUid, Function.identity()));

        Date callTime = DateUtil.getNowDatetime();
        int reachNum = 0;
        int lateNum = 0;
        int askLeaveNum = 0;
        int notReachNum = 0;
        int noHourNum = 0;
        List<CaCallNames> newList = new ArrayList<>();
        for (int i = 0; i < array.size(); i++) {
            JSONObject object = array.getJSONObject(i);
            String memberUid = object.getString("memberUid");
            String memberName = object.getString("memberName");
            Integer callStatus = object.getInteger("callStatus");
            String mob = object.getString("mob");

            // 补缺状态
            Integer makeupStatus = null;
            // 参与状态 1.已到 2.迟到 3.请假 4.未到
            if (callStatus.equals(1)) {
                reachNum += 1;
            } else if (callStatus.equals(2)) {
                lateNum += 1;
            } else if (callStatus.equals(3)) {
                askLeaveNum += 1;
                makeupStatus = 0;
            } else if (callStatus.equals(4)) {
                notReachNum += 1;
                makeupStatus = 0;
            } else if (callStatus.equals(-1)) {
                noHourNum += 1;
            }

            CaCallNames data = callNamesMap.get(memberUid);
            Long memberId = memberMap.get(memberUid);
            data = ScheduleUtil.newCallName(data, lesson, corpUid, lessonStoreUid, lessonStoreName, staffUid, staffName,
                    teacherName, memberId, memberUid, memberName, mob, null, callStatus, makeupStatus, 1, callTime, "");
            // 添加点名人信息
            data.setCallStaffUid(staffUid);
            data.setCallStaffName(staffName);
            newList.add(data);
        }
        // 活动点名，更新会员的参与状态对应的数量
        boolean l = scheduleLessonService.callNames(lessonStoreUid, lessonUid, teacherName, reachNum, lateNum, askLeaveNum, notReachNum,
                noHourNum, lesson.getStatus(), staffUid, staffName, callTime);
        if (!l)
            throw new Exception("更新活动的点名信息失败");
        // 创建并更新活动的点名记录
        callNameService.saveOrUpdateBatch(newList);
        // 是第一次活动点名，更新活动表的已活动数量
        if (lesson.getStatus().equals(0))
            scheduleService.addUseLessonNum(lessonStoreUid, lesson.getScheduleUid());

        return R.ok();
    }

    @ApiOperation(value = "导出会员活动记录")
    @PostMapping(value = "/exportList", produces = "application/vnd.ms-excel;charset=UTF-8")
    public void exportList(
            HttpServletResponse response,
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "会员姓名/手机号/社团名/活动室名") @RequestParam(value = "keyword", required = false) String keyword,
            @ApiParam(value = "参与状态 1.已到 2.迟到 3.请假 4.未到") @RequestParam(value = "callStatus", required = false) Integer callStatus,
            @ApiParam(value = "活动状态 -1.已取消 0.未进行 1.已进行 2.已完成") @RequestParam(value = "status", required = false) Integer status,
            @ApiParam(value = "主讲导读username") @RequestParam(value = "teacherUid", required = false) String teacherUid,
            @ApiParam(value = "活动服务uid") @RequestParam(value = "projectUid", required = false) String projectUid,
            @ApiParam(value = "活动开始日期") @RequestParam(value = "beginDate", required = false) String beginDate,
            @ApiParam(value = "活动结束日期") @RequestParam(value = "endDate", required = false) String endDate
    ) throws Exception {
        // 默认查当月
        if (StringUtils.isBlank(keyword) && StringUtils.isBlank(teacherUid) && StringUtils.isBlank(projectUid)
                && callStatus == null && status == null
                && (StringUtils.isBlank(beginDate) || StringUtils.isBlank(endDate))
        ) {
            Date monthMinDate = DateUtil.getMonthMinDate();
            Date monthMaxDate = DateUtil.getMonthMaxDate();
            beginDate = DateUtil.getDefaultTime2DateStr(monthMinDate);
            endDate = DateUtil.getDefaultTime2DateStr(monthMaxDate);
        }

        List<CaCallNames> list = callNameService.getMemberCallListV3(corpUid, storeUid, keyword, callStatus, beginDate,
                endDate, teacherUid, projectUid, status, null, null);

        List<CallNameVo> voList = new ArrayList<>();
        int firstStartRow = 1;
        int firstEndRow = 0;
        // 需要合并的行号
        List<RowBean> firstRows = new ArrayList<>();
        // 需要合并的列号
        List<Integer> firstColumns = Lists.newArrayList(0, 1);

        if (CollectionUtils.isNotEmpty(list)) {
            Map<String, List<CaCallNames>> map = list.stream().collect(Collectors.groupingBy(CaCallNames::getMemberUid));

            for (Map.Entry<String, List<CaCallNames>> entry : map.entrySet()) {
                String memberUid = entry.getKey();
                List<CaCallNames> callNamesList = entry.getValue();
                int lessonNum = callNamesList.size();

                firstEndRow += lessonNum;
                // 合并必须包含2个或更多单元格
                if (firstStartRow != firstEndRow)
                    firstRows.add(new RowBean(firstStartRow, firstEndRow));
                firstStartRow += lessonNum;

                for (CaCallNames call : callNamesList) {
                    CallNameVo nameVo = new CallNameVo();
                    nameVo.setLessonNum(lessonNum);
                    nameVo.setStoreName(call.getStoreName());
                    nameVo.setTeachDate(call.getTeachDate() + " " + call.getBeginTime() + "-" + call.getEndTime());
                    nameVo.setWeekName(call.getWeekName());
                    nameVo.setClassName(call.getClassName());
                    nameVo.setProductName(call.getProductName());
                    nameVo.setStageName(call.getStageName());
                    nameVo.setRoomName(call.getRoomName());
                    nameVo.setTeacherName(call.getTeacherName());
                    nameVo.setMemberName(call.getMemberName());
                    nameVo.setMob(call.getMob());
                    nameVo.setStudentTypeName(call.getStudentTypeName());
                    nameVo.setUnitAmount(NepUtil.nullToZero(call.getUnitAmount()));

                    WriteCellData<String> richCallStatus = new WriteCellData<>();
                    richCallStatus.setType(CellDataTypeEnum.RICH_TEXT_STRING);
                    nameVo.setCallStatusName(richCallStatus);
                    RichTextStringData textStringDataCallStatus = new RichTextStringData();
                    richCallStatus.setRichTextStringDataValue(textStringDataCallStatus);
                    // 字体样式
                    WriteFont writeFont = new WriteFont();
                    // 字体大小
                    writeFont.setFontHeightInPoints((short) 14);
                    short fontColor = IndexedColors.RED.getIndex();
                    if (null != call.getCallStatus())
                        if (call.getCallStatus().equals(1) || call.getCallStatus().equals(2)) {
                            fontColor = IndexedColors.GREEN.getIndex();
                        }
                    // 字体颜色
                    writeFont.setColor(fontColor);
                    String csName = StringUtils.isNotBlank(call.getCallStatusName()) ? call.getCallStatusName() : "";
                    textStringDataCallStatus.setTextString(csName);
                    textStringDataCallStatus.applyFont(writeFont);


                    WriteCellData<String> richStatus = new WriteCellData<>();
                    richStatus.setType(CellDataTypeEnum.RICH_TEXT_STRING);
                    nameVo.setStatusName(richStatus);
                    RichTextStringData textStringDataStatus = new RichTextStringData();
                    richStatus.setRichTextStringDataValue(textStringDataStatus);
                    // 字体样式
                    WriteFont writeFont2 = new WriteFont();
                    // 字体大小
                    writeFont2.setFontHeightInPoints((short) 14);
                    short fontColor2 = IndexedColors.RED.getIndex();
                    // 活动状态 -1.已取消 0.未活动 1.已活动 2.已完成
                    String statusName = "";
                    if (call.getStatus().equals(-1)) {
                        statusName = "已取消";
                    } else if (call.getStatus().equals(0)) {
                        statusName = "未进行";
                    } else if (call.getStatus().equals(1)) {
                        statusName = "已进行";
                    } else if (call.getStatus().equals(2)) {
                        statusName = "已完成";
                        fontColor2 = IndexedColors.GREEN.getIndex();
                    }
                    // 字体颜色
                    writeFont2.setColor(fontColor2);
                    textStringDataStatus.setTextString(statusName);
                    textStringDataStatus.applyFont(writeFont2);

                    if (call.getCloseTime() != null)
                        nameVo.setCloseTime(DateUtil.getDefaultTimeStr(call.getCloseTime()));

                    WriteCellData<String> richHourType = new WriteCellData<>();
                    richHourType.setType(CellDataTypeEnum.RICH_TEXT_STRING);
                    nameVo.setHourType(richHourType);
                    RichTextStringData textStringDataHourType = new RichTextStringData();
                    richHourType.setRichTextStringDataValue(textStringDataHourType);
                    // 字体样式
                    WriteFont writeFont3 = new WriteFont();
                    // 字体大小
                    writeFont3.setFontHeightInPoints((short) 14);
                    short fontColor3 = IndexedColors.RED.getIndex();
                    String hourTypeName = "";
                    if (null != call.getStatus() && call.getStatus().equals(2)) {
                        Integer freeStatus = call.getFreeStatus();
                        Integer callHourType = call.getHourType();
                        hourTypeName = call.getHourTypeName();
                        if (freeStatus.equals(1)) {
                            if (callHourType.equals(1) || callHourType.equals(2) || callHourType.equals(3)) {
                                fontColor3 = IndexedColors.GREEN.getIndex();
                            }
                        }
                    }
                    // 字体颜色
                    writeFont3.setColor(fontColor3);
                    textStringDataHourType.applyFont(writeFont3);
                    textStringDataHourType.setTextString(hourTypeName);

                    voList.add(nameVo);
                }
            }
        }
        String fileName = "会员活动记录" + beginDate + "至" + endDate;
        ExcelHandler.exportMergeExcel(response, voList, CallNameVo.class, fileName, "会员活动记录", firstRows, firstColumns);
    }

    @ApiOperation(value = "根据服务uid获取点名记录")
    @PostMapping(value = "/getMemberCallRecords", produces = "application/json; charset=UTF-8")
    public R<Object> getMemberCallRecords(
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "服务uid") @RequestParam(value = "serviceUid") String serviceUid
    ) {
        List<CaCallNamesDto> list = callNameService.getByServiceUidV2(serviceUid);
        return R.ok(list);
    }

}